﻿<!DOCTYPE html>
<html class="theme theme-white">
<head>
<meta charset="utf-8">
<title>redis学习---数据持久化</title>
<link href="https://www.zybuluo.com/static/assets/template-theme-white.css" rel="stylesheet" media="screen">
<style type="text/css">

#wmd-preview h1  {
    color: #0077bb; /* 将标题改为蓝色 */
}</style>
</head>
<body class="theme theme-white">
<div id="wmd-preview" class="wmd-preview wmd-preview-full-reader"><div class="md-section-divider"></div><div class="md-section-divider"></div><h1 data-anchor-id="2l21" id="redis学习-数据持久化">redis学习---数据持久化</h1><div class="md-section-divider"></div><h2 data-anchor-id="e030" id="目录">目录</h2><ul data-anchor-id="kslc">
<li>简介</li>
<li>RDS <br>
<ul><li>简介</li>
<li>持久化流程</li>
<li>触发方式</li>
<li>配置方式</li>
<li>命令方式</li>
<li>优点</li>
<li>缺点</li></ul></li>
<li>AOF <br>
<ul><li>简介</li>
<li>持久化流程</li>
<li>配置方式</li>
<li>AOF重写原理</li>
<li>AOF重写流程</li></ul></li>
</ul><div class="md-section-divider"></div><h2 data-anchor-id="vakw" id="1-简介">1. 简介</h2><p data-anchor-id="x1lb">Redis支持两种方式的持久化，一种是RDB方式、另一种是AOF方式。前者会根据指定的规则“定时”将内存中的数据存储在硬盘上，而后者在每次执行命令后将命令本身记录下来。两种持久化方式可以单独使用其中一种，也可以将这两种方式结合使用</p><div class="md-section-divider"></div><h2 data-anchor-id="8eme" id="2-rds">2. RDS</h2><div class="md-section-divider"></div><h3 data-anchor-id="0h6a" id="21-简介">2.1 简介：</h3><p data-anchor-id="j3vy">当符合一定条件时，Redis会单独创建（fork）一个子进程来进行持久化，会先将数据写入到一个临时文件中，等到持久化过程都结束了，再用这个临时文件替换上次持久化好的文件</p><div class="md-section-divider"></div><h3 data-anchor-id="7zdu" id="22-持久化流程">2.2 持久化流程</h3><p data-anchor-id="3gwr">当符合一定条件时，redis会单独创建一个fork，fork的作用时复制一个与当前进程一样的集成，新进程的所有数据（变量、环境变量、程序计数器等）数值都和原进程一致，但是是一个全新的进程，并作为原进程的子进程，然后先将数据集写入临时文件，写入成功后，再替换之前的文件，用二进制压缩存储。</p><p data-anchor-id="js60"><img src="http://chengqj.com/static/images/redis/RDB%E7%9A%84fork%E6%B5%81%E7%A8%8B.png" alt="rds持久化流程"></p><div class="md-section-divider"></div><h3 data-anchor-id="4tkn" id="23-触发方式">2.3 触发方式</h3><ul data-anchor-id="t230">
<li>根据配置规则进行自动快照</li>
<li>用户执行SAVE或者GBSAVE命令</li>
<li>执行FLUSHALL命令</li>
<li>执行主从复制(replication)时</li>
</ul><div class="md-section-divider"></div><h3 data-anchor-id="g5y8" id="24-配置方式">2.4 配置方式</h3><p data-anchor-id="nfi9"><strong>格式：</strong> save 时间 键的个数 <br>
<strong>说明：</strong> 在第一个时间的配置范围内被更改的键次数大于后面一个值时触发 <br>
<strong>默认配置：</strong></p><div class="md-section-divider"></div><pre class="prettyprint linenums prettyprinted" data-anchor-id="gl6u"><ol class="linenums"><li class="L0"><code class="language-properties"><span class="com">#900秒有1次改变</span></code></li><li class="L1"><code class="language-properties"><span class="pln">save </span><span class="lit">900</span><span class="pln"> </span><span class="lit">1</span></code></li><li class="L2"><code class="language-properties"><span class="com">#300秒有10次改变</span></code></li><li class="L3"><code class="language-properties"><span class="pln">save </span><span class="lit">300</span><span class="pln"> </span><span class="lit">10</span></code></li><li class="L4"><code class="language-properties"><span class="com">#60秒有10000次改变</span></code></li><li class="L5"><code class="language-properties"><span class="pln">save </span><span class="lit">60</span><span class="pln"> </span><span class="lit">10000</span></code></li><li class="L6"><code class="language-properties"><span class="com">#是否启用压缩</span></code></li><li class="L7"><code class="language-properties"><span class="pln">rdbcompression yes</span></code></li><li class="L8"><code class="language-properties"><span class="com">#数据存放文件</span></code></li><li class="L9"><code class="language-properties"><span class="pln">dbfilename </span><span class="kwd">dump</span><span class="pun">.</span><span class="pln">rdb</span></code></li><li class="L0"><code class="language-properties"><span class="com">#数据存放路径</span></code></li><li class="L1"><code class="language-properties"><span class="pln">dir </span><span class="pun">./</span></code></li></ol></pre><div class="md-section-divider"></div><h3 data-anchor-id="a0f1" id="25-命令方式">2.5 命令方式</h3><table data-anchor-id="ohha" class="table table-striped-white table-bordered">
<thead>
<tr>
 <th>命令</th>
 <th>说明</th>
</tr>
</thead>
<tbody><tr>
 <td>save</td>
 <td>同步做快照，做快照期间，会阻塞来自客户端请求，不建议</td>
</tr>
<tr>
 <td>bgsave</td>
 <td>异步做快照，做快照期间，不会阻塞来自客户端请求</td>
</tr>
<tr>
 <td>FLUSHALL</td>
 <td>会清除所有的redis内存中的数据，执行该命令后，只要存在快照规则，都会执行一次快照操作，如果没有快照规则，不执行</td>
</tr>
</tbody></table><div class="md-section-divider"></div><h3 data-anchor-id="254v" id="26-优点">2.6 优点：</h3><p data-anchor-id="by4a">整个过程中，主进程是不进行任何IO操作的，这就确保了极高的性能。如果需要进行大规模数据的恢复，且对于数据恢复的完整性不是非常敏感，那RDB方式要比AOF方式更加的高效</p><div class="md-section-divider"></div><h3 data-anchor-id="iial" id="27-缺点">2.7 缺点：</h3><p data-anchor-id="8bzo">最后一次持久化后的数据可能丢失</p><div class="md-section-divider"></div><h2 data-anchor-id="7yoz" id="3-aof">3. AOF</h2><div class="md-section-divider"></div><h3 data-anchor-id="ng3i" id="31-简介">3.1 简介：</h3><p data-anchor-id="hfyk">AOF可以将Redis执行的每一条写命令追加到硬盘文件中，这一过程会降低Redis的性能，但大部分情况下这个影响是能够接受的，另外使用较快的硬盘可以提高AOF的性能</p><div class="md-section-divider"></div><h3 data-anchor-id="ajxd" id="32-持久化流程">3.2 持久化流程</h3><p data-anchor-id="mgo1">以日志的形式记录服务器所处理的每一个写、删除操作，查询操作不会记录，以文本的方式记录，可以打开文件看到详细的操作记录</p><p data-anchor-id="ixvt"><img src="http://www.chengqj.com/static/images/redis/AOF%E6%8C%81%E4%B9%85%E5%8C%96%E6%B5%81%E7%A8%8B.png" alt="AOF持久化流程" title=""></p><div class="md-section-divider"></div><h3 data-anchor-id="7oc6" id="33-配置方式">3.3 配置方式</h3><div class="md-section-divider"></div><pre class="prettyprint linenums prettyprinted" data-anchor-id="izsf"><ol class="linenums"><li class="L0"><code class="language-properties"><span class="com">#是否开启</span></code></li><li class="L1"><code class="language-properties"><span class="pln">appendonly yes </span></code></li><li class="L2"><code class="language-properties"><span class="com">#开启后文件存储路径</span></code></li><li class="L3"><code class="language-properties"><span class="pln">appendfilename </span><span class="str">"appendonly.aof"</span></code></li><li class="L4"><code class="language-properties"><span class="com">#表示的是当目前的AOF文件大小超过上一次重写时的AOF文件大小的百分之多少时会再次进行重写，如果之前没有重写过，则以启动时AOF文件大小为依据</span></code></li><li class="L5"><code class="language-properties"><span class="kwd">auto</span><span class="pun">-</span><span class="pln">aof</span><span class="pun">-</span><span class="pln">rewrite</span><span class="pun">-</span><span class="pln">percentage </span><span class="lit">100</span></code></li><li class="L6"><code class="language-properties"><span class="com">#表示限制了允许重写的最小AOF文件大小，通常在AOF文件很小的情况下即使其中有很多冗余的命令我们也并不太关心</span></code></li><li class="L7"><code class="language-properties"><span class="kwd">auto</span><span class="pun">-</span><span class="pln">aof</span><span class="pun">-</span><span class="pln">rewrite</span><span class="pun">-</span><span class="pln">min</span><span class="pun">-</span><span class="pln">size </span><span class="lit">64mb</span></code></li></ol></pre><div class="md-section-divider"></div><h3 data-anchor-id="dn2z" id="34-aof重写原理">3.4 AOF重写原理</h3><p data-anchor-id="nkox">对同一个key每进行一次操作都会新增一条日志，长久以往会有大量垃圾数据，占用文件空间，redis会对AOF的文件自动进行优化，主要配置就是通过 <br>
auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64mb重写后的新AOF文件包含了回复当前数据所需的最小命令集合</p><div class="md-section-divider"></div><h3 data-anchor-id="l85u" id="35-aof重写流程">3.5 AOF重写流程</h3><p data-anchor-id="bv9r"><img src="http://www.chengqj.com/static/images/redis/AOF%E9%87%8D%E5%86%99%E6%B5%81%E7%A8%8B.png" alt="AOF重写流程" title=""></p><ol data-anchor-id="lxii">
<li>主进程fork一个子进程来进行AOF重写</li>
<li>子进程进行AOF重写（类似于快照，全量遍历内存中数据，然后逐个写入到aof文件中）</li>
<li>服务正常提供，如这是有客户端请求，主进程会把数据更新操作，缓存到aof_rewrite_buf中。（单独开辟一块缓存来存储重写期间收到的命令）</li>
<li>子进程重写完后把缓存中数据追加到新aof中</li>
<li>临时文件替换老的aof文件</li>
<li>后续请求数据正常写入aof文件</li>
</ol><hr></div>
</body>
</html>